import React, { useEffect, useState, forwardRef, useRef } from 'react';
import { DeleteOutlined, EyeOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { Button, Modal, Upload, Progress, App } from 'antd';

import styles from './index.module.scss';

const getBase64 = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = (error) => reject(error);
    });
};
const getColor = () => {
    const rootElement = document.documentElement;
    const primaryColor = getComputedStyle(rootElement).getPropertyValue('--rt-primary-color').trim();
    return primaryColor || '';
};
const getNumber = o => {
    if (typeof o === 'number' && !isNaN(o)) return o || 1;
    if (typeof o === 'string' && !isNaN(parseInt(o)) && isFinite(o)) return Number(o) || 1;
    return 1;
}
const processFile = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (event) => {
            let img = new Image();
            img.src = event.target.result;

            img.onload = () => {
                resolve({
                    width: img.width,
                    height: img.height,
                    size: file.size,
                });
                img = null; // 清理资源
            };

            img.onerror = (error) => {
                reject(new Error(`无法加载图片: ${file.name}`));
            };
        };

        reader.readAsDataURL(file);
    });
};

export default forwardRef((props, ref) => {
    const { message } = App.useApp();
    const { disabled=false, shape='', limit, isAvatar=true, widthRange=[], heightRange=[], maxSize=0, sizeEnum=[], totalPixels=0 } = props;
    const [previewOpen, setPreviewOpen] = useState(false);
    const [previewImage, setPreviewImage] = useState('');
    const [fileList, setFileList] = useState([]);
    const uploader = useRef(null);
    const conicColors = {
        '0%': '#ffccc7',
        '50%': '#ffe58f',
        '100%': '#00C261',
    };
    const isSingle = 1 === getNumber(limit);

    const handleCancel = () => setPreviewOpen(false);
    const handlePreview = async (file) => {
        if (!file.url && !file.preview) {
            file.preview = await getBase64(file.originFileObj);
        }
        setPreviewImage(file.url || file.preview);
        setPreviewOpen(true);
    };
    const handleChange = (info) => {
        let newFileList = [...info.fileList];
        const fileNumber = getNumber(limit);
        const endIndex = newFileList.length;
        const startIndex = endIndex - fileNumber;

        // 从后往前取文件数量，保证是选择中的最后N个文件
        newFileList = newFileList.slice(startIndex, endIndex).map((file) => {
            if(file.status === 'done') {
                if (OK_CODE === file?.response?.code?.toString()) {
                    let u = file.response.data;
                    file.url = u;
                }
            }

            return file;
        }).filter(Boolean);

        setFileList(newFileList);

        // 没有上传中的文件，说明上传已完成
        const noUploading = !newFileList.filter(i => i.status === 'uploading').length;
        if(noUploading) {
            props.onChange(newFileList.map(i => i.url).join(','));
        }
    };
    const uploadButton = (
        <button ref={uploader} style={{border: 0, background: 'none', cursor: 'pointer',pointerEvents:'none'}}>
            <PlusOutlined />
            <div style={{marginTop: 8}}>
                上传图片
            </div>
        </button>
    );
    const getSingleButton = () => {
        const file = fileList[0];
        const status = file?.status;
        const percent = file?.percent || 0;

        return (
            'done' === status ?
                <div className={styles['single-image']}>
                    <img src={fileList[0]?.url} alt="" />
                    {
                        disabled ?
                            null
                            :
                            <div className={styles['mask']}>
                                <div className={styles['button']}><UploadOutlined/></div>
                            </div>
                    }
                </div>
                :
                'uploading' === status ?
                    <div className={styles['single-loading']}>
                        <Progress size="small" type="circle" percent={percent} strokeColor={conicColors} />
                    </div>
                    :
                    uploadButton
        );
    };

    const itemRender = (originNode, file, fileList, {download, preview, remove}) => {
        const imgUrl = file.url || file.thumbUrl || '';

        return (
            <div className={`${styles['upload-item']} ${'circle' === shape ? styles['circle'] : ''}`}>
                {'done' === file.status && imgUrl ? <img src={imgUrl} alt="" /> : null}
                {
                    'done' === file.status ?
                        <div className={styles['actions']}>
                            <div className={styles['btn']}>
                                <div className={styles['button']} onClick={e => {e.stopPropagation();preview();}}><EyeOutlined/></div>
                                { disabled ? null : <div className={styles['button']} onClick={e => {e.stopPropagation();remove();}}><DeleteOutlined/></div> }
                            </div>
                        </div>
                        :
                        null
                }
                {
                    'uploading' === file.status ?
                        <div className={styles['loading']}>
                            <Progress size="small" type="circle" percent={parseInt(file.percent)} strokeColor={conicColors} />
                        </div>
                        :
                        null
                }
            </div>
        );
    };

    const beforeUpload = async (file, fileList) => {
        if((!widthRange||!widthRange.length) && (!heightRange||!heightRange.length) && !maxSize && (!totalPixels||!totalPixels.length)) return Promise.resolve();

        return new Promise(async (resolve, reject) => {
            const {width, height, size} = await processFile(file) || {};
            if(Array.isArray(sizeEnum) && sizeEnum.length && !(sizeEnum||[]).includes(`${width}x${height}`)) {
                message.error(`参考图片大小不符合要求，可使用 [工具箱 - 图片裁剪] 来调整`);
                return Upload.LIST_IGNORE;
            }
            if(widthRange && (width < widthRange[0] || width > widthRange[1])) {
                message.error(`图片宽度：[${widthRange.toString()}]`);
                return Upload.LIST_IGNORE;
            }
            if(heightRange && (height < heightRange[0] || height > heightRange[1])) {
                message.error(`图片高度：[${heightRange.toString()}]`);
                return Upload.LIST_IGNORE;
            }
            if(maxSize && size > maxSize) {
                message.error(`图片应小于：${maxSize} Bytes`);
                return Upload.LIST_IGNORE;
            }
            if(width*height < totalPixels[0] || width*height > totalPixels[1]) {
                message.error(`图片总像素(宽*高)范围：[${totalPixels.toString()}]`);
                return Upload.LIST_IGNORE;
            }
            resolve();
        }).catch(e => Upload.LIST_IGNORE);
    };

    useEffect(() => {
        let urls = props.value || [];

        if(typeof props.value === 'string') {
            urls = props.value.split(',');
        }

        let imageList = urls.filter(Boolean).map(item => {
            let o = fileList.find(i => i.url === item);
            return ({
                uid: o?.uid || item,
                name: item,
                status: 'done',
                url: item,
            })
        });

        setFileList(imageList);

    }, [props.value]);

    return (
        <>
            <Upload
                className={`${styles['upload']} ${styles[shape] || ''}`}
                action={props.action}
                listType="picture-card"
                fileList={fileList}
                showUploadList={!isAvatar}
                onPreview={handlePreview}
                onChange={handleChange}
                multiple={isAvatar ? false : !isSingle}
                accept={props.accept}
                maxCount={99} // 最多一次上传99个文件
                itemRender={itemRender}
                beforeUpload={beforeUpload}
                data={props.data || {}}
                headers={{token: localStorage.getItem('accessToken')}}
                disabled={disabled}
            >
                {
                    isAvatar ?
                        getSingleButton()
                        :
                        fileList.length >= (getNumber(limit)) ? null : uploadButton
                }
            </Upload>

            <Modal
                open={previewOpen}
                title="资源预览"
                footer={null}
                onCancel={handleCancel}
                maskClosable={false}
            >
                <img
                    alt=""
                    style={{
                        width: '100%',
                        userSelect: 'none'
                    }}
                    src={previewImage}
                />
            </Modal>
        </>
    );
});